import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
import { GlobalData, Dict, District, JavaValidator } from '@/typography/interface/types/global-data'
import { validResponse } from '@TG/kit/request'
import { isNotEmpty } from '@TG/kit/validate'
import store from '@TG/store'
import { dictList, districtList, javaValidatorList } from '@TG/api/global-data'

const getDictKey = (type: string, value: string) => {
  return `${type}-${value}`
}

const initDistrict = (districtStorer: Map<string, District>, districtList: District[]) => {
  if (isNotEmpty(districtList)) {
    districtList.forEach(district => {
      const value = district.value
      const children = district.children || []
      districtStorer.set(value, district)
      initDistrict(districtStorer, children)
    })
  }
}

@Module({ dynamic: true, store, name: 'globalDataModule' })
class GlobalDataModule extends VuexModule implements GlobalData {
  private dictStorer = new Map<string, Dict>()
  private dictTypeStorer = new Map<string, Array<Dict>>()
  private districtStorer = new Map<string, District>()
  private districtList: District[] = []
  private javaValidatorStorer = new Map<string, JavaValidator>()
  private javaValidatorList: JavaValidator[] = []

  @Mutation
  private INIT_DICT(dictList: Dict[]) {
    if (isNotEmpty(dictList)) {
      dictList.forEach(dict => {
        const type = dict.type
        const value = dict.value
        const dictKey = getDictKey(type, value)
        this.dictStorer.set(dictKey, dict)
        let dictList = this.dictTypeStorer.get(type) || []
        dictList.push(dict)
        this.dictTypeStorer.set(type, dictList)
      })
    }
  }

  @Mutation
  private INIT_DISTRICT(districtList: District[]) {
    initDistrict(this.districtStorer, districtList)
    if (isNotEmpty(districtList)) {
      this.districtList.push(...districtList)
    }
  }

  @Mutation
  private INIT_JAVA_VALIDATOR(javaValidatorList: JavaValidator[]) {
    if (isNotEmpty(javaValidatorList)) {
      javaValidatorList.forEach(javaValidator => {
        const clazz = javaValidator.clazz
        this.javaValidatorStorer.set(clazz, javaValidator)
      })
      this.javaValidatorList.push(...javaValidatorList)
    }
  }

  @Mutation
  private GET_DICT_STORER() {
    return this.dictStorer
  }

  @Mutation
  private GET_DICT_TYPE_STORER() {
    return this.dictTypeStorer
  }

  @Mutation
  private GET_DISTRICT_STORER() {
    return this.districtStorer
  }

  @Mutation
  private GET_DISTRICT_LIST() {
    return this.districtList
  }

  @Mutation
  private GET_JAVA_VALIDATOR_STORER() {
    return this.javaValidatorStorer
  }

  @Mutation
  private GET_JAVA_VALIDATOR_LIST() {
    return this.javaValidatorList
  }

  @Action
  public async initGlobalData() {
    console.log('初始化全局数据.开始 ...')
    const dictResponse = await dictList()
    if (validResponse(dictResponse)) {
      const dictList: Dict[] = dictResponse.data
      this.INIT_DICT(dictList)
    }
    console.log('字典初始化完成 ...')
    const districtResponse = await districtList()
    if (validResponse(districtResponse)) {
      const districtList: District[] = districtResponse.data
      this.INIT_DISTRICT(districtList)
    }
    console.log('地区初始化完成 ...')
    const javaValidatorResponse = await javaValidatorList()
    if (validResponse(javaValidatorResponse)) {
      const javaValidatorList: JavaValidator[] = javaValidatorResponse.data
      this.INIT_JAVA_VALIDATOR(javaValidatorList)
    }
    console.log('JAVA 检验器初始化完成 ...')
    console.log('初始化全局数据.完成 ...')
  }

  @Action
  public getDictLabel(payload: { type: string, value: string }) {
    const { type, value } = payload
    const dictKey = getDictKey(type, value)
    const dictStorer = this.GET_DICT_STORER()
    const dict = dictStorer.get(dictKey)
    return dict?.label || value
  }

  @Action
  public getDictList(type: string) {
    const dictTypeStorer = this.GET_DICT_TYPE_STORER()
    return dictTypeStorer.get(type) || []
  }

  @Action
  public getDistrictLabel(value: string) {
    const districtStorer = this.GET_DISTRICT_STORER()
    const district = districtStorer.get(value)
    return district?.label || value
  }

  @Action
  public getDistrictList() {
    return this.GET_DISTRICT_LIST()
  }

  @Action
  public getJavaValidatorLabel(clazz: string) {
    const javaValidatorStorer = this.GET_JAVA_VALIDATOR_STORER()
    const javaValidator = javaValidatorStorer.get(clazz)
    return javaValidator?.label || clazz
  }

  @Action
  public getJavaValidatorParamDescr(clazz: string) {
    const javaValidatorStorer = this.GET_JAVA_VALIDATOR_STORER()
    const javaValidator = javaValidatorStorer.get(clazz)
    let paramDescr = ''
    if (isNotEmpty(javaValidator)) {
      const paramDescrs = javaValidator?.paramDescrs || []
      if (isNotEmpty(paramDescrs)) {
        paramDescr = paramDescrs.join('<br />')
      }
    }
    return paramDescr
  }

  @Action
  public getJavaValidatorList() {
    return this.GET_JAVA_VALIDATOR_LIST()
  }
}

export const globalDataModule = getModule(GlobalDataModule)
